<template>
    <ul ref="contexmenu_wrap" class="contexmenu_wrap"></ul>
</template>

<script setup>
const props = defineProps({
    active_elem: {
        type: Object,
        required: false
    },
    menu_list: {
        type: Array,
        required: false
    },
    theme: {
        type: String,
        required: false
    },
    allow_select: {
        type: Boolean,
        required: false,
        default: null
    },
    leaveHide_timeout: {
        type: Number,
        required: false
    },
    ctmu: {
        type: Object,
        required: false
    }
})

// 函数集合
const groupSet = {}

// 通过sha256编码出，防止多个菜单实例撞车
import cryptoJs from 'crypto-js'
const wrap_id = 'SHA256_' + cryptoJs.SHA256(JSON.stringify(props)).toString()


import { ref, onMounted, nextTick, shallowRef, watch } from 'vue'
import { defaultIcon, expandRight, titleIcon, linkIcon } from '@/assets/data/contextmenu_list'
import { trigger_event } from '@/assets/lib/function.lib'

const list = shallowRef(props.menu_list ?? props.ctmu.list)
const activeElem = shallowRef(props.active_elem ?? props.ctmu.elem)
const initFunction = shallowRef(props.init_function ?? props.ctmu.initFn)

//
const menuSize = shallowRef(props.menu_size ?? props.ctmu.size)

// 主题
const theme = shallowRef(props.theme ?? props.ctmu.theme)

// 允许选择
const allow_select = shallowRef(props.allow_select ?? props.ctmu.select)

const contexmenu_wrap = shallowRef(null)
// 鼠标离开多久，子菜单消失
const leaveHide_timeout = shallowRef(props.leaveHide_timeout ?? props.ctmu.leaveHide ?? 0)

// 需要所在元素的区域才会被激活
const target_elem = ref(null)

const activeElem_attr = 'data-rcm-233'

if (window.contexmenu_activeElem?.length) {
    window.contexmenu_activeElem.push(activeElem.value)
} else {
    window.contexmenu_activeElem = [activeElem.value]
}

onMounted(() => {
    $(activeElem.value).attr(activeElem_attr, '')
    $(contexmenu_wrap.value).addClass('style-' + theme.value).css({
        width: menuSize.value ? menuSize.value : '10rem'
    })

    if (!allow_select.value) { contexmenu_wrap.value.style.userSelect = 'none' }
    nextTick(() => {

        window.wx = $(window).width()
        window.wy = $(window).height()

        window.addEventListener('resize', () => {
            window.wx = $(window).width()
            window.wy = $(window).height()
        })


        $(contexmenu_wrap.value).attr('id', wrap_id)
        read(list.value)
        // 监听右键
        document.addEventListener('contextmenu', event => {
            // 判断是否是目标元素
            let allow = true;

            const closeset = event.target.closest(activeElem.value)
            if (!target_elem.value && closeset) {
                target_elem.value = closeset
            }
            if (activeElem.value == '*' || closeset) {
                window.contexmenu_activeElem.forEach(e => {
                    if (activeElem.value != e && event.target.closest(e)) {
                        if ($(e).find(activeElem.value).length == 0) {
                            window.getSelection().removeAllRanges()
                            allow = false
                        }
                    }
                })
                if (allow) {
                    event.preventDefault(); // 阻止默认的右键功能
                    display_contextmenu(event)
                    if (!activeElem.registered) listener()
                }
            } else if (event.target.closest('#' + wrap_id)) event.preventDefault();
        })

        // 隐藏
        $(document).on('click', event => {
            let group = $(event.target.closest('.group'))
            if (!group.length) group = $(event.target).find('>.group')

            const cd = group.closest('li').data('clickDispear') == 'false'
            const dc = event.target.closest('.drag_ctrl')

            if ((!group.siblings('ul.sub_opn').length &&
                group.data('type') != 'splitline' &&
                group.data('type') != 'title') &&
                !(cd || dc)
            ) $(contexmenu_wrap.value).hide()
        })

    })
})

function display_contextmenu(event) {
    // 菜单大小
    const wrap = $('#' + wrap_id)
    const ww = wrap.width()
    const wh = wrap.height()

    // 鼠标位置
    const x = event.pageX
    const y = event.pageY

    // 以百分比设置菜单位置
    let px = (x / window.wx) * 100
    let py = (y / window.wy) * 100

    // 判断是否超出边界，并纠正
    if (window.wx - x <= ww + 10) {
        const pww = (ww / window.wx) * 100
        px -= pww
    }
    if (window.wy - y <= wh + 10) {
        const pwh = (wh / window.wy) * 100
        py -= pwh
    }

    wrap.css({
        display: 'block',
        top: py + '%',
        left: px + '%'
    })
}

function listener() {
    // 已被注册
    activeElem.registered = true

    $(`#${wrap_id} li`).get().forEach(e => {
        // opnPos(e, true)
        $(e).on('mouseenter', () => {
            opnPos(e)
        }).on('mouseleave', () => {
            setTimeout(() => {
                $(e).find('>.sub_opn').hide().css({
                    zIndex: 10
                })
            }, $(e).data('subHide_timeout') ?? leaveHide_timeout.value)
        })
    })

    function opnPos(thisElem) {
        const sub = $(thisElem).find('>.sub_opn')
        if (sub.length) {
            // 子选项总体的大小
            // const sw = sub.find('>li:first').width()
            const sh = sub.height()

            // 当前选项距离top: 0的距离
            // 父元素 - 前排的元素高度
            const lt = $(thisElem).position().top

            sub.show()
            sub.css({
                zIndex: 12
            })

            sub.css({
                left: '100%',
            })
            /* if (x - sw - 10 <= 0) {
                sub.css({
                    left: '100%',
                })
            } */
            if (window.wx - sub.offset().left - sub.width() <= 10) {
                sub.css({
                    left: '-100%'
                })
            }

            sub.css({
                top: lt + 'px'
            })
            if (window.wy - sub.offset().top - sub.height() <= 10) {
                sub.css({
                    top: `calc(100% - ${sh}px)`
                })
            }
        }
    }
}

function read(obj, par) {
    if (typeof obj == 'object') {
        if (Array.isArray(obj)) {
            // 数组
            obj.forEach(e => {
                readObject(e, par)
            })
        } else {
            // 对象
            readObject(obj, par)
        }
    }
}

function readObject(obj, par) {
    let init = {
        // 基本属性

        // 选项内容
        text: '未命名选项',
        // 选项开头的图标
        icon: defaultIcon[1],
        // 单个选项会执行的函数
        fn: (elem, wrap) => { },

        // 单独or对象传入，每个选项都会执行的函数，在fn之前执行
        dfn: (elem, wrap) => { },

        /**
         * 选项类型 [data-v-type]
         * 'option': 正常的选项
         * 'title': 标题
         * 'subtitle': 二级标题
         * 'splitline': 分割线，text、icon属性无效
         * 'empty': 空
         * 'link': 链接，与href、target属性配合
         * 'seekbar': 拖拽条
         */
        type: 'option',
        titleIcon: titleIcon[0],

        maxTitle: 6,
        maxText: 24,

        // 快捷键
        key: [],
        // 是否需要在打开菜单的基础上执行快捷键
        needshow: false,

        // 展示快捷键的长度
        maxKeyDesc: 8,

        // 是否可以拖拽
        drag: false,

        // 单击消失
        clickDispear: true,

        // data属性，作用于 elem.parent
        data: '',

        href: '/',
        target: '_blank',
        linkIcon: linkIcon[0],

        // 如果false，elem、elem.parent 均会添加[data-notallowed-click]属性
        allowClick: true,

        // 初始化sub的默认参数
        subInit: null,
        subInit_deep: false,

        // 鼠标离开经过多长时间子菜单消失
        subHide_timeout: null,

        // 拖拽条选项
        seekbar: {
            // 当前位置
            pos: 0,
            min: -100,
            max: 100,
            origin_color: '#eee',
            cover_color: '#00bd7e',
            drag_color: '#39495e',
            interval: null
        },

        // option id 空 = text
        oid: null
    }

    if (initFunction.value) {
        init.dfn = (elem, wrap) => initFunction.value(elem, wrap)
    }

    for (let k in obj) {
        if (typeof obj[k] == 'object' && !Array.isArray(obj[k])) {
            try {
                for (let j in obj[k]) {
                    // 只遍历一层嵌套
                    init[k][j] = obj[k][j]
                }
            } catch {
                init[k] = obj[k]
            }
        } else {
            init[k] = obj[k]
        }
    }

    // init.sub = []
    if (Array.isArray(init.sub)) {
        init.sub.forEach((e, i) => {
            if (typeof e == 'string' || typeof e == 'number') {
                init.sub[i] = {
                    text: e.toString()
                }
            }
        })
    }

    // 子项初始化
    if (init.subInit && init.sub) {
        if (typeof obj.sub == 'object') {
            if (Array.isArray(obj.sub)) {
                obj.sub.forEach(e => {
                    setAttr(e)
                })
            } else {
                setAttr(obj.sub)
            }
        }

        function setAttr(item) {
            for (let attr in init.subInit) {
                item[attr] = init.subInit[attr]

                item.subInit = (init.subInit_deep || init.subInit.deep) ? init.subInit : null
            }
        }
    }

    if (init.type == 'title' && !obj.text) init.text = '未命名标题'

    addOpn(init, par)
}

function addOpn(obj, par) {
    const parent = par ?? $('#' + wrap_id)
    obj.oid = obj.oid ?? obj.text

    const li = $(`<li oid="${wrap_id + obj.oid}"></li>`)
    const group = $('<div class="group"></div>')

    li.append(group).data('clickDispear', obj.clickDispear.toString())
    parent.append(li)

    // 裁剪超过长度的选项描述
    {
        // 标题
        obj.text = limiteTextLength(obj.text, obj.maxTitle, 'title', obj.type)
        obj.text = limiteTextLength(obj.text, obj.maxText, 'option', obj.type)
    }
    let desc = ''
    {
        // 判断组合键
        let keys = ''
        if (obj.key.length >= 1) {
            let ctrl = '&&!event.ctrlKey';
            let shift = '&&!event.shiftKey';
            let alt = '&&!event.altKey';
            desc = obj.key.map((res, i) => {
                function add(str) {
                    keys += keys.length == 0 ? 'event.' + str : '&&event.' + str
                }

                if (capitalUp(res) == 'Ctrl' || capitalUp(res) == 'Control') {
                    add('ctrlKey')
                    ctrl = ''
                    return ' Ctrl'
                } else if (capitalUp(res) == 'Shift') {
                    add('shiftKey')
                    shift = ''
                    return ' Shift'
                } else if (capitalUp(res) == 'alt') {
                    add('altKey')
                    alt = ''
                    return ' Alt'
                } else {
                    add(`key.toUpperCase()=="${capitalUp(res)}"`)
                    return ' ' + res.toUpperCase()
                }

            }).join('')

            keys += ctrl + shift + alt;
        }
        keys ? isKeyActive(keys, str => group.click(), obj.needshow) : null
    }
    {
        // 添加属性
        if (typeof obj.data == 'object') {
            if (Array.isArray(obj.data)) {
                obj.data.forEach(e => {
                    addData(e)
                })
            } else {
                addData(obj.data)
            }

            function addData(obj) {
                const key = Object.keys(obj)
                li.data(key, obj[key])
            }
        } else {
            li.data('data', obj.data)
        }
    }
    {
        // 不允许点击
        if (!obj.allowClick) {
            group.attr('data-notallowed-click', '')
            li.attr('data-notallowed-click', '')
        }
    }

    desc = desc.trim().split(' ').join(' + ')

    group.data('type', obj.type)
    li.attr('data-v-' + obj.type, '')

    group.parent = li
    group.wrapper = li.parent()
    // 重要新特性，支持跨选项修改值
    /*
    console.log(elem.getOption('色相'))
    console.log(elem.getGroup('色相').set_seekbar(12))
    */
    // 选项组集合
    group.getOption = oid => li.parent().find(`li[oid="${wrap_id + oid}"]`)
    group.getGroup = oid => {
        return groupSet[wrap_id + oid]
    }

    groupSet[wrap_id + obj.oid] = group


    watch(() => target_elem.value, newVal => {
        trigger_event('find_target_elem', group[0], {
            target: newVal
        })
    })

    // 类型判断
    switch (obj.type) {
        case 'subtitle':
            group.append(`<p>${obj.text}</p>`)
            break
        case 'option':
            const icon = $(`<span class="menu_icon">${obj.icon}</span>`)
            const text = $(`<p>${obj.text}</p>`)
            group.append(icon)
            group.append(text)

            group.textElem = text;

            // 子项消失延迟
            if (obj.subHide_timeout) li.data('subHide_timeout', obj.subHide_timeout)

            if (obj.sub) {
                group.append($(`<span class="expand">${expandRight[1]}</span>`))
                const son = $('<ul class="sub_opn left"></ul>')
                li.append(son)
                read(obj.sub, son)
            } else {
                group.append($(`<i class="desc">${desc}</i>`))
            }
            break;
        case 'splitline':
            break;
        case 'title':
            group.html(`${obj.titleIcon}<p>${obj.text}</p>`)
            group.textElem = group.find('>p')
            break;
        case 'empty':
            break;
        case 'link': {
            // const link = $(`<a href="${obj.href}" target="${obj.target}"></a>`)
            const link = $(`<a href="javascript:;"></a>`)
            const icon = $(`<span class="menu_icon">${linkIcon}</span>`)
            const text = $(`<p>${obj.text}</p>`)
            const _desc = $(`<i class="desc">${desc}</i>`)

            link.append(icon)
            link.append(text)
            link.append(_desc)

            group.append(link)

            group.linkElem = link
            li.on('click', () => {
                window.open(obj.href, obj.target)
                /* event.preventDefault()
                link.click(() => [

                    event.stopPropagation()
                ]) */
            })
        }
            break;
        case 'seekbar':
            let offset = 0

            const setting = obj.seekbar
            group.html()
            const desc_wrap = $('<div class="seekbar_desc"></div>')
            desc_wrap.html(`<span class="menu_icon">${obj.icon}</span><p>${obj.text}</p>`)

            const offset_show = $(`<input class="current_percent" type="number" min="${setting.min}" max="${setting.max}"></input>`)
            desc_wrap.append(offset_show)

            const seekbar = document.createElement('div')
            const drag_ctrl = document.createElement('span')
            seekbar.className = 'seekbar'
            drag_ctrl.className = 'drag_ctrl'
            seekbar.appendChild(drag_ctrl)

            group.append(desc_wrap)
            group[0].appendChild(seekbar)

            drag_ctrl.style.background = setting.drag_color ?? '#39495e'

            // 获取原始背景色
            const origin_background = setting.origin_color ?? window.getComputedStyle(seekbar).background.split(')')[0] + ')'
            // 被覆盖的背景色
            const cover_color = setting.cover_color ?? '#00bd7e'
            // 滑动间隔
            const itv_list = setting.interval ? (() => {
                const list = [];
                let current = setting.min;
                while (current <= setting.max) {
                    list.push(current);
                    current += setting.interval;
                }
                // 确保最后一个点不超过max
                if (list[list.length - 1] > setting.max) {
                    list[list.length - 1] = setting.max;
                } else if (list[list.length - 1] < setting.max) {
                    list.push(setting.max);
                }
                return list;
            })() : null

            // 计算总范围
            const range = setting.max - setting.min;

            setting.pos == Number(setting.pos) ? set_seekbar(setting.pos) : null
            offset_show.val(setting.pos)

            offset_show.on('focus', () => {
                offset_show.on('input', () => {
                    const val = parseFloat(offset_show.val());
                    if (!isNaN(val)) {
                        trigger_dragEvent(val)
                    }
                })
            })

            group[0].onmouseenter = event => {
                function handleKeyup(event) {
                    switch (event.key.toLowerCase()) {
                        case 'a':
                            trigger_dragEvent(limit_offset(parseFloat(offset_show.val()) - ditv, true))
                            break;

                        case 'd':
                            trigger_dragEvent(limit_offset(parseFloat(offset_show.val()) + ditv, true))
                            break;
                    }
                }

                // 添加滚轮事件处理
                function handleWheel(event) {
                    event.preventDefault();
                    const currentVal = parseFloat(offset_show.val());
                    if (isNaN(currentVal)) return;

                    // 步进值
                    const step = setting.interval;
                    let newVal;

                    // 滚轮向下滚动 - 增加
                    if (event.deltaY > 0) {
                        newVal = currentVal + step;
                    }
                    // 滚轮向上滚动 - 减少
                    else if (event.deltaY < 0) {
                        newVal = currentVal - step;
                    }

                    trigger_dragEvent(limit_offset(newVal, true));
                }

                window.addEventListener('keyup', handleKeyup)
                // 修复：添加 { passive: false } 选项
                group[0].addEventListener('wheel', handleWheel, { passive: false })

                group[0].addEventListener('mouseleave', () => {
                    window.removeEventListener('keyup', handleKeyup)
                    group[0].removeEventListener('wheel', handleWheel)
                })
            }

            group[0].onmousedown = event => {
                if (event.target.tagName == 'INPUT') return
                change_drag_pos(event)

                function handleMouseMove(event) {
                    change_drag_pos(event)
                }

                function handleMouseUp() {
                    document.body.removeEventListener('mousemove', handleMouseMove)
                    document.body.removeEventListener('mouseup', handleMouseUp)

                    trigger_event('drag-done', group[0])
                }

                document.body.addEventListener('mousemove', handleMouseMove)
                document.body.addEventListener('mouseup', handleMouseUp)

                function change_drag_pos(event) {
                    const percent = (event.pageX - seekbar.getBoundingClientRect().left) / seekbar.clientWidth;
                    const val = setting.min + percent * range;
                    trigger_dragEvent(limit_offset(val, true))
                }
            }

            function limit_offset(_offset, itv) {
                // 修正范围限制顺序
                _offset = _offset <= setting.min ? setting.min : _offset >= setting.max ? setting.max : _offset

                if (itv && itv_list) {
                    let minDist = Infinity;
                    let closestVal = itv_list[0];
                    for (let i = 0; i < itv_list.length; i++) {
                        const dist = Math.abs(itv_list[i] - _offset);
                        if (dist < minDist) {
                            minDist = dist;
                            closestVal = itv_list[i];
                        }
                    }
                    _offset = closestVal;
                }

                return _offset;
            }

            function trigger_dragEvent(val) {
                set_seekbar(val)
                trigger_event('drag', group[0], {
                    offset: val
                })
            }

            function set_seekbar(val) {
                // 使用正确的计算公式
                offset = (val - setting.min) / range * 100

                offset_show.val(val)
                group.val = val

                drag_ctrl.style.left = offset + '%'
                // 修正渐变背景
                seekbar.style.backgroundImage =
                    `linear-gradient(90deg, ${cover_color} 0%, ${cover_color} ${offset}%, ${origin_background} ${offset}%, ${origin_background} 100%)`
            }

            group._set_seekbar = new_offset => {
                set_seekbar(new_offset)
                return group
            }

            group.set_seekbar = new_offset => {
                set_seekbar(new_offset)
                trigger_event('drag-done', group[0])
                return group
            }

            group.apply = () => {
                trigger_dragEvent(limit_offset(group.val))

                console.log(limit_offset(group.val));

                return group
            }

            break;
    }

    if (obj.drag) drag(li[0], contexmenu_wrap.value)

    // 先执行默认方法
    obj.dfn(group, $('#' + wrap_id))
    // 再执行自定义方法
    obj.fn(group, $('#' + wrap_id))
}


function limiteTextLength(str, len, type, ctype) {
    if (ctype == type && str.length >= len) {
        str = str.substr(0, len) + '…'
    }
    return str
}

function capitalUp(str) {
    return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
}

if (!window.regKey) window.regKey = {}
function isKeyActive(str, call, needshow) {
    if (!window.regKey[str]) {
        // 确保只执行一次
        window.regKey[str] = true

        let allow = true
        let menu_display = true;
        window.addEventListener('keydown', event => {
            menu_display = needshow ? !$(contexmenu_wrap.value).is(':hidden') : true
            if (allow && menu_display && eval(str)) {
                event.preventDefault()
                call()
                allow = false
                setTimeout(() => {
                    allow = true
                }, 500)
            }
        })
    }
}

function drag(ctrl, elem) {
    const wrap = $(contexmenu_wrap.value)
    let offsetX = 0;
    let offsetY = 0;


    let transition = ''
    let zIndex = 10
    $(ctrl).addClass('drag_ctrl')

    const handleMouseDown = event => {
        transition = wrap.css('transition')
        zIndex = wrap.css('z-index')
        wrap.css({
            transition: 'none',
            zIndex: zIndex + 1
        })

        offsetX = event.clientX - elem.offsetLeft;
        offsetY = event.clientY - elem.offsetTop;

        window.addEventListener('mousemove', handleMouseMove);
    }

    const handleMouseMove = event => {
        $('*').attr('data-v-233', '')
        elem.style.left = event.clientX - offsetX + 'px';
        elem.style.top = event.clientY - offsetY + 'px';
    }

    const handleMouseUp = () => {
        $('*').removeAttr('data-v-233')
        wrap.css({
            transition: transition,
            zIndex: zIndex
        })
    }

    ctrl.addEventListener('mousedown', handleMouseDown)
    window.addEventListener('mouseup', () => {
        handleMouseUp()
        window.removeEventListener('mousemove', handleMouseMove);
    })
}
</script>

<style lang="less">
@wrap_size_h: 1.2rem;
@wrap_size_w: 10rem;
@expand_icon_size: 0.9rem;
@menu_icon_size: 1rem;

@menu_bg: #fff;

@option_fontsize: 1em;
@optionkey_fontsize: 0.1em;

.contexmenu_wrap {
    position: fixed;
    top: 0;
    left: 0;
    width: @wrap_size_w;
    padding: 0;
    box-shadow: 0.06rem 0.06rem 0.3rem #666;

    display: none;
    z-index: 10;
    transition: all 0.2s;
    background: @menu_bg;

    &:hover {
        box-shadow: 0.06rem 0.06rem 0.3rem #000;
    }

    .group {
        box-sizing: content-box !important;
        white-space: nowrap;
        background: @menu_bg;
    }

    .drag_ctrl {
        cursor: grab !important;
    }

    li {
        list-style-type: none;
        font-size: @option_fontsize;

        /* img,
        svg {
            vertical-align: middle;
        } */

        .menu_icon {
            position: relative;
            display: inline-block;
            top: calc((@wrap_size_h - @menu_icon_size) / 2);
            width: @menu_icon_size;
            height: @menu_icon_size;

            path {
                fill: #233;
            }
        }

        .desc {
            font: 400 @optionkey_fontsize auto !important;
            position: absolute;
            right: 0.5rem;
            top: calc((@wrap_size_h/2 - @optionkey_fontsize) / 2);


            color: #999;
        }
    }

    li[data-v-option] {
        // display: flex;
        // position: relative;
        // top: 100%;
        // left: 100%;

        >.group {
            cursor: pointer;
            position: relative;
            display: flex;
            width: 100%;
            height: @wrap_size_h;
            line-height: @wrap_size_h;

            padding: .3rem 0;


            &:hover {
                background: #ccc;
                color: #fff;
            }
        }

        .expand {
            position: absolute;
            right: 0;
            top: calc((@wrap_size_h - @expand_icon_size) / 2);
            width: @expand_icon_size;
            height: @expand_icon_size;

            svg {
                right: 0;
                z-index: 1;

                path {
                    fill: #666;
                }
            }
        }

        .sub_opn {
            display: none;
            position: absolute;

            box-shadow: 1px 1px 0.1rem #00f619;

            &.left {
                left: -@wrap_size_w;
            }

            &.right {
                left: @wrap_size_w;
            }
        }

        &:hover {
            >.group {
                background: #00bd7e;
            }

            .group {
                transition: all 0.3s;
                text-shadow: 0.02rem 0.02rem 0.01rem #8e2b00;

                &:hover {
                    text-shadow: inset 0.03rem 0.03rem 0.01rem #f64a00;
                }

                .desc {
                    color: #eee;
                }
            }

            .sub_opn {
                box-sizing: content-box;
                border: 0.1rem solid #88b0e3;

                &:hover {
                    border: 0.1rem solid #1373f2;
                }
            }
        }
    }

    li[data-v-title] {
        @title_h: @wrap_size_h * 1.1;
        @title_icon_size: @menu_icon_size * 1.1;

        position: relative;

        * {
            font: 800 @title_icon_size "Microsoft Yahei";
        }

        .group {
            height: calc(@title_h + 0.5em);
            text-align: center;
            display: flex;
            justify-content: center;
            background: #01d38d;
            position: relative;
            z-index: 1;
            transition: all 0.3s;

            // &:hover {
            //     box-shadow: 1px 1px 0.5rem #02a26c;
            // }

            p {
                margin-left: 0.2em;
            }
        }

        svg,
        img {
            position: relative;
            top: calc(@title_h - @title_icon_size);
            // left: -0.2em;
            width: @title_icon_size;
            height: @title_icon_size;
        }
    }

    li[data-v-subtitle] {
        @subtitle_h: @wrap_size_h * 0.86;
        @subtitle_icon_size: @menu_icon_size * 0.86;

        position: relative;

        * {
            font: 400 @subtitle_icon_size "Microsoft Yahei";
        }

        .group {
            height: calc(@subtitle_h + 0.5em);
            text-align: center;
            display: flex;
            justify-content: center;
            background: #01d38d;
            position: relative;
            z-index: 1;
            transition: all 0.3s;

            p {
                margin-left: 0.2em;
            }
        }

        svg,
        img {
            position: relative;
            top: calc(@subtitle_h - @subtitle_icon_size);
            width: @subtitle_icon_size;
            height: @subtitle_icon_size;
        }
    }



    li[data-v-splitline] {
        position: relative;
        height: 1rem;

        &::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 2%;
            width: 96%;
            height: 1px;
            background: #ccc;
        }

        background: @menu_bg;

        &+li>::before {
            background: transparent;
        }
    }

    li[data-v-empty] {
        .group {
            width: 100%;
            height: @wrap_size_h;
        }
    }

    li[data-v-link] {
        .group {
            a {
                position: relative;
                display: flex;
                width: 100%;
                height: @wrap_size_h;
                line-height: @wrap_size_h;
            }
        }
    }

    li[data-v-seekbar] {
        @seekbar_h: 0.5rem;
        @dragctrl_h: 1.2rem;
        @dragctrl_w: 0.6rem;

        .group {
            height: @wrap_size_h * 2.5;
            transition: all 0.2s;

            &:hover {
                background: #00bd7e33;
            }

            .seekbar_desc {
                position: relative;
                height: @wrap_size_h;
                line-height: @wrap_size_h;
                display: flex;

                input.current_percent {
                    position: absolute;
                    right: .1em;
                    width: 4.5em;
                    height: @wrap_size_h * 0.8;
                    bottom: @wrap_size_h * 0.1;
                    outline: none;
                    border: none;
                    background: #ffffffcc;

                    &:hover {
                        outline: 2px solid #ccc;
                    }
                }
            }

            .seekbar {
                position: relative;
                top: calc(@wrap_size_h*1.5/2 - @seekbar_h / 2);
                width: calc(98% - @dragctrl_w * 2);
                height: @seekbar_h;
                background: #eee;
                // background: #00bd7e;
                border-radius: 1rem;
                padding-right: calc(@dragctrl_w / 2);
                margin: 0 @dragctrl_w;

                .drag_ctrl {
                    position: relative;
                    top: calc(50% - @dragctrl_h/2);
                    display: block;
                    height: @dragctrl_h;
                    width: @dragctrl_w;
                    border-radius: 1rem;
                    background: #39495e;
                }
            }
        }
    }
}


@media (min-width: 0) and (max-width: 600px) {
    .desc {
        display: none;
    }
}
</style>

<style lang="less">
@menu_bg: transparent !important;

.style-transparent {
    box-shadow: 0.06rem 0.06rem 0.3rem #666;

    background: @menu_bg;

    &:hover {
        box-shadow: 0.06rem 0.06rem 0.3rem #000;
    }

    .group {
        background: @menu_bg;
    }


    li[data-v-option] {
        .desc {
            color: #999;
        }

        >.group {

            &:hover {
                color: #fff;
            }
        }

        .expand {
            svg {
                path {
                    fill: #666;
                }
            }
        }

        .sub_opn {
            box-shadow: 1px 1px 0.1rem #00f619;
        }

        &:hover {
            >.group {
                background: #00000066;
            }

            .group {
                text-shadow: 0.02rem 0.02rem 0.01rem #8e2b00;

                &:hover {
                    text-shadow: inset 0.03rem 0.03rem 0.01rem #f64a00;
                }

                .desc {
                    color: #eee;
                }
            }

            .sub_opn {
                border: 0.1rem solid #88b0e3;

                &:hover {
                    border: 0.1rem solid #1373f2;
                }
            }
        }

        .menu_icon {
            path {
                fill: #000;
            }
        }
    }

    li[data-v-title] {

        * {
            font: 800 auto "Microsoft Yahei";
        }
    }

    li[data-v-splitline] {

        &::before {
            background: #ccc;
        }

        background: @menu_bg;

        &+li>::before {
            background: transparent;
        }
    }
}
</style>